package utils.fileConvert;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.linuxense.javadbf.*;
import entity.DbfParam;
import entity.ExcConvertToDbfCTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import utils.object.UtilValidate;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author Chen Yuan
 * @create 2021-12-20  10:42
 */
@Slf4j
public class DBFUtil {

	/**
	 * 读取 DBF 格式文件
	 *
	 * @param file      DBF 文件流
	 * @param columnMap DBF 文件表头名称与实体类对象字段映射关系 - "表头名称:实体类字段名称", 示例 "id:id,password:password", 表头为中文时 "主键:id,密码:password"
	 * @param clazz     对象
	 * @return
	 */
	public static <T> List<T> readDbfByFile(MultipartFile file, String columnMap, Class<T> clazz) {
		List<T> result = null;
		try {
			// 去除字符串中的空格
			columnMap = columnMap.replace(" ", "");
			DbfParam dbfParam = new DbfParam();
			dbfParam.setBuf(file.getBytes())
					.setIsStream(true)
					.setColumnMap(DBFUtilBase.getMap(columnMap));
			result = DBFUtilBase.commonReadDbf(dbfParam, clazz);
		} catch (Exception e) {
			log.error("×××× readExcByFile ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}

	/**
	 * 读取 DBF 格式文件
	 *
	 * @param file  DBF 文件流
	 * @param clazz 对象
	 * @return
	 */
	public static <T> List<T> readDbfByFile(MultipartFile file, Class<T> clazz) {
		List<T> result = null;
		try {
			if (UtilValidate.isEmpty(clazz)) {
				return result;
			}
			DbfParam dbfParam = new DbfParam();
			dbfParam.setBuf(file.getBytes())
					.setIsStream(true);
			result = DBFUtilBase.commonReadDbf(dbfParam, clazz);
		} catch (Exception e) {
			log.error("×××× readExcByFile ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}

	/**
	 * 读取 DBF 格式文件
	 *
	 * @param file DBF 文件流
	 * @return
	 */
	public static <T> List<T> readDbfByFile(MultipartFile file) {
		List<T> result = null;
		try {
			DbfParam dbfParam = new DbfParam();
			dbfParam.setBuf(file.getBytes())
					.setIsStream(true);
			Class clazz = JSONObject.class;
			result = DBFUtilBase.commonReadDbf(dbfParam, clazz);
		} catch (Exception e) {
			log.error("×××× readExcByFile ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}

	/**
	 * 读取 DBF 格式文件
	 *
	 * @param filePath  DBF 文件路径
	 * @param columnMap DBF 文件表头名称与实体类对象字段映射关系 - "表头名称:实体类字段名称", 示例 "id:id,password:password", 表头为中文时 "主键:id,密码:password"
	 * @param clazz     对象
	 * @return
	 */
	public static <T> List<T> readDbfByPath(String filePath, String columnMap, Class<T> clazz) {
		List<T> result = null;
		try {
			// 去除字符串中的空格
			columnMap = columnMap.replace(" ", "");
			DbfParam dbfParam = new DbfParam();
			dbfParam.setFilePath(filePath)
					.setIsStream(false)
					.setColumnMap(DBFUtilBase.getMap(columnMap));
			result = DBFUtilBase.commonReadDbf(dbfParam, clazz);
		} catch (Exception e) {
			log.error("×××× readDbfByPath ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}

	/**
	 * 读取 DBF 格式文件
	 *
	 * @param filePath DBF 文件路径
	 * @param clazz    对象
	 * @return
	 */
	public static <T> List<T> readDbfByPath(String filePath, Class<T> clazz) {
		List<T> result = null;
		try {
			if (UtilValidate.isEmpty(clazz)) {
				return result;
			}
			DbfParam dbfParam = new DbfParam();
			dbfParam.setFilePath(filePath)
					.setIsStream(false);
			result = DBFUtilBase.commonReadDbf(dbfParam, clazz);
		} catch (Exception e) {
			log.error("×××× readDbfByPath ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}

	/**
	 * 读取 DBF 格式文件
	 *
	 * @param filePath DBF 文件路径
	 * @return
	 */
	public static <T> List<T> readDbfByPath(String filePath) {
		List<T> result = null;
		try {
			DbfParam dbfParam = new DbfParam();
			dbfParam.setFilePath(filePath)
					.setIsStream(false);
			Class clazz = JSONObject.class;
			result = DBFUtilBase.commonReadDbf(dbfParam, clazz);
		} catch (Exception e) {
			log.error("×××× readDbfByPath ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}


	/**
	 * 导出 DBF 格式文件, 到本地
	 *
	 * @param filePath   DBF 存放路径
	 * @param entityList 待处理的数据列表, 需要是实体类列表
	 * @param clazz      entityList 对应的对象
	 * @return 操作结果
	 */
	public static <T> String exportDbfByPath(String filePath, List entityList, Class<T> clazz) {
		String result = null;
		try {
			DbfParam dbfParam = new DbfParam();
			dbfParam.setFilePath(filePath)
					.setIsStream(false)
					.setDataList(entityList)
					.setIsEntity(true);
			result = DBFUtilBase.commonExportDbf(dbfParam, clazz);
		} catch (Exception e) {
			log.error("×××× exportDbfByPath ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}

	/**
	 * 导出 DBF 格式文件, 到本地
	 *
	 * @param filePath   DBF 存放路径
	 * @param entityList 待处理的数据列表, 需要是实体类列表
	 * @param columnMap  DBF 文件表头名称与实体类对象字段映射关系 - "表头名称:实体类字段名称", 示例 "id:id,password:password", 表头为中文时 "主键:id,密码:password"
	 * @param clazz      entityList 对应的对象
	 * @return 操作结果
	 */
	public static <T> String exportDbfByPath(String filePath, List entityList, String columnMap, Class<T> clazz) {
		String result = null;
		try {
			// 去除字符串中的空格
			columnMap = columnMap.replace(" ", "");
			DbfParam dbfParam = new DbfParam();
			dbfParam.setFilePath(filePath)
					.setIsStream(false)
					.setDataList(entityList)
					.setIsEntity(true)
					.setColumnMap(DBFUtilBase.getMap(columnMap));
			result = DBFUtilBase.commonExportDbf(dbfParam, clazz);
		} catch (Exception e) {
			log.error("×××× exportDbfByPath ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}


	/**
	 * 导出 DBF 格式文件, 到本地
	 *
	 * @param filePath  DBF 存放路径
	 * @param fieldList DBF 文件字段信息列表,
	 *                  - 必填参数: name, type, length, decimalCount(小数点后位数,若当前数据类型有小数则必填)
	 *                  - 注意: setType() 必须在 setLength() 前执行, 否则会报错
	 * @param rowData   数据列表
	 *                  - 注意: 数据的格式、顺序必须和  fieldList 中的一致
	 * @return 操作结果
	 */
	public static <T> String exportDbfByPath(String filePath, List<DBFField> fieldList, List<Object[]> rowData) {
		String result = null;
		try {
			DbfParam dbfParam = new DbfParam();
			dbfParam.setFilePath(filePath)
					.setIsStream(false)
					.setFieldList(fieldList)
					.setRowData(rowData)
					.setIsEntity(false);
			result = DBFUtilBase.commonExportDbf(dbfParam, null);
		} catch (Exception e) {
			log.error("×××× exportDbfByPath ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}

	/**
	 * 导出 DBF 格式文件, 浏览器下载
	 *
	 * @param response   HTTP 响应
	 * @param entityList 待处理的数据列表, 需要是实体类列表
	 * @param clazz      entityList 对应的对象
	 * @param fileName   文件名, 默认为 当前时间戳 , (.dbf)可写可不写,
	 * @return 操作结果
	 */
	public static <T> String exportDbfByHttp(HttpServletResponse response, List entityList, Class<T> clazz, String fileName) {
		String result = null;
		try {
			DbfParam dbfParam = new DbfParam();
			dbfParam.setResponse(response)
					.setIsStream(true)
					.setDataList(entityList)
					.setIsEntity(true)
					.setFileName(fileName);
			result = DBFUtilBase.commonExportDbf(dbfParam, clazz);
		} catch (Exception e) {
			log.error("×××× exportDbfByHttp ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}

	/**
	 * 导出 DBF 格式文件, 浏览器下载
	 *
	 * @param response   HTTP 响应
	 * @param entityList 待处理的数据列表, 需要是实体类列表
	 * @param columnMap  DBF 文件表头名称与实体类对象字段映射关系 - "表头名称:实体类字段名称", 示例 "id:id,password:password", 表头为中文时 "主键:id,密码:password"
	 * @param clazz      entityList 对应的对象
	 * @param fileName   文件名, 默认为 当前时间戳 , (.dbf)可写可不写,
	 * @return 操作结果
	 */
	public static <T> String exportDbfByHttp(HttpServletResponse response, List entityList, String columnMap, Class<T> clazz, String fileName) {
		String result = null;
		try {
			// 去除字符串中的空格
			columnMap = columnMap.replace(" ", "");
			DbfParam dbfParam = new DbfParam();
			dbfParam.setResponse(response)
					.setIsStream(true)
					.setDataList(entityList)
					.setIsEntity(true)
					.setColumnMap(DBFUtilBase.getMap(columnMap))
					.setFileName(fileName);
			result = DBFUtilBase.commonExportDbf(dbfParam, clazz);
		} catch (Exception e) {
			log.error("×××× exportDbfByHttp ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}

	/**
	 * 导出 DBF 格式文件, 浏览器下载
	 *
	 * @param response  HTTP 响应
	 * @param fieldList DBF 文件字段信息列表,
	 *                  - 必填参数: name, type, length, decimalCount(小数点后位数,若当前数据类型有小数则必填)
	 *                  - 注意: setType() 必须在 setLength() 前执行, 否则会报错
	 * @param rowData   数据列表
	 *                  - 注意: 数据的格式、顺序必须和  fieldList 中的一致
	 * @param fileName  文件名, 默认为 当前时间戳 , (.dbf)可写可不写,
	 * @return 操作结果
	 */
	public static <T> String exportDbfByHttp(HttpServletResponse response, List<DBFField> fieldList, List<Object[]> rowData, String fileName) {
		String result = null;
		try {
			DbfParam dbfParam = new DbfParam();
			dbfParam.setResponse(response)
					.setIsStream(true)
					.setFieldList(fieldList)
					.setRowData(rowData)
					.setIsEntity(false)
					.setFileName(fileName);
			result = DBFUtilBase.commonExportDbf(dbfParam, null);
		} catch (Exception e) {
			log.error("×××× exportDbfByHttp ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}


	public static void main(String[] args) throws Exception {
		List<ExcConvertToDbfCTO> list = null;
		String pathOfDbf = "C:/Users/zovan/Desktop/user.dbf";
		String pathOfDbf2 = "C:/Users/zovan/Desktop/user2.dbf";
		String readMap = "id:id,password:password,username:username,user_style:userStyle,source:source,updateDt:updateDt";
		String exportMap = "id:id,password:password,username:username,userStyle:user_style,delFlag:del_flag,updateDt:updateDt";

		File file = null;
		FileInputStream inputStream = null;
		MultipartFile multipartFile = null;

		// 1. 通过实体类配置的 @DBF 注解获取表头和字段名的映射关系
		//Map<String, String> columnMap = DBFUtil.getColumnMap(JSONObject.class, null);
		//System.out.println(JSON.toJSONString(columnMap));

		// 2. 通过文件流读取 DBF
		//file = new File(pathOfDbf);
		//inputStream = new FileInputStream(file);
		//multipartFile = new MockMultipartFile(file.getName(), file.getName(), ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
		//list = DBFUtil.readDbfByFile(multipartFile, ExcConvertToDbfCTO.class);
		//log.info(JSON.toJSONString(list.get(5).getUsername()));

		// 3. 通过文件路径读取 DBF
		//list = DBFUtil.readDbfByPath(pathOfDbf, ExcConvertToDbfCTO.class);
		//list = DBFUtil.readDbfByPath(pathOfDbf2);

		// 4. 通过对象列表生成 DBF
		//String s = DBFUtil.exportDbfByPath(pathOfDbf2, list, ExcConvertToDbfCTO.class);
		//String s = DBFUtil.exportDbfByPath(pathOfDbf2, list, exportMap, ExcConvertToDbfCTO.class);

		// 5. 通过自己构建的 DBF 信息对象\数据导出
		//List<DBFField> fieldList = new ArrayList<>();
		//DBFField field = new DBFField();
		//field.setName("姓名");
		//field.setType(DBFDataType.CHARACTER);
		//field.setLength(100);
		//fieldList.add(field);
		//
		//field=new DBFField();
		//field.setName("birth");
		//field.setType(DBFDataType.DATE);
		//field.setLength(8);
		//fieldList.add(field);
		//
		//field=new DBFField();
		//field.setName("docNo");
		//field.setType(DBFDataType.NUMERIC);
		//field.setLength(10);
		//fieldList.add(field);
		//
		//field=new DBFField();
		//field.setName("体重");
		//field.setType(DBFDataType.NUMERIC);
		//field.setLength(10);
		//field.setDecimalCount(2);
		//fieldList.add(field);
		//
		////准备数据
		//List<Object[]> rowDataList=new ArrayList<Object[]>();
		//
		//Object[] rowData = new Object[fieldList.size()];
		//rowData[0] = "呵呵呵";
		//rowData[1] = new Date();
		//rowData[2] = 1233;
		//rowData[3] = new BigDecimal("1.22");
		//rowDataList.add(rowData);
		//
		//rowData = new Object[fieldList.size()];
		//rowData[0] = "哈哈哈";
		//rowData[1] = null;
		//rowData[2] = 754;
		//rowData[3] = new BigDecimal("2.1");
		//rowDataList.add(rowData);
		//
		//String s = DBFUtil.exportDbfByPath(pathOfDbf2, fieldList, rowDataList);
		//System.out.println(s);

		log.info(JSON.toJSONString(list));

		System.out.println(DBFDataType.MEMO.getMaxSize());
	}
}
